<!DOCTYPE html>
<html lang="cn">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="shortcut icon" href="favicon2.ico"/>
    <link rel="bookmark" href="favicon2.ico"/>
    <title>Sky弹琴3.0</title>
</head>
<body>
<!--     给一个数组，加上分布行数 x 自动布局
    div中套上即可
    将其动画化canvas画出来，css旋转即可 -->
    <!-- <div id="keysArea"></div> -->
    <div id="tool">
        <div id="bulletin" onclick="switchOptionsDisplayStatus()" class="noCopy"></div>
        <table id="options" class="noCopy">
            <tr>
                <th>功能简介</th>
                <th>操作按钮</th>
                <th>备注</th>
            </tr>
            <tr>
                <td>音量调节</td>
                <td class="copy">
                    <input type="button" value="声音" onclick="setVolumeNum()" id="setvolume">
                    <!-- <meter value="3" min="0" max="10">十分之三</meter> -->
                </td>
                <td>可以开关声音，也可以调节音量</td>
            </tr>
            <tr>
                <td>放大缩小</td>
                <td class="copy">
                    <button onclick="document.body.style.zoom = 1;">1x</button>
                    <button onclick="document.body.style.zoom = 2;">2x</button>
                    <button onclick="document.body.style.zoom = 3;">3x</button>
                    <input type="number" id="zoomSize" class="inputUO" />
                    <button onclick="document.body.style.zoom = document.querySelector('#zoomSize').value;">修改大小</button>
                </td>
                <td>可以更改整个页面(body)的大小</td>
            </tr>
            <tr>
                <td>选择模式</td>
                <td id="modeKey" class="copy"></td>
                <td>点击按钮快速选择乐器音频</td>
            </tr>
            <tr>
                <td>自动演奏</td>
                <td class="copy">
                    <button onclick="startAutoPlay()">启动</button>
                    <button onclick="pauseAutoPlay(this)">暂停</button>
                    <button onclick="stopAutoPlay()">停止</button>
                    <br>
                    <textarea id="inputScore" cols="30" rows="10" class="inputTextarea" placeholder='这里输入谱子，只支持默认解析方式。格式："A1,B1,C1,123,A1,A2,A3,A4,A5,A6,A7"'></textarea>
                </td>
                <td>输入谱子并点击启动即可自动弹奏</td>
            </tr>
        </table>
    </div>
</body>
</html>


<script>
    var performer = {
        update: `V3.1
        <br>    1.新增更新介绍
        <br>    2.新增音量开关
        <br>    3.删除一个log显示
        <br>    4.开始制作Auto.js同步版
        `
        , scoreHandle: (score, map, firstHandle)=>{
            if (typeof firstHandle == "function") {
                score = firstHandle(score);
            }
            let result = [];
            score.forEach((s) => {
                if (map[s]) {
                    result.push(map[s]);
                } else if (0 < s) {
                    result.push(s);
                } else {
                    console.log("缺失映射，丢弃：[" + s + "]");
                }
            });
            return result;
        }
        , exec: {
            precision: 1
            , data: []
            , currentIndex: 0
            , totalIndex: ()=>{ return data.length;}
            , timesSpeed: 1
            , pause: false
            , stop: false
            , remainingTime: 0
            /**
             * 执行函数，包含功能，拓展外部的控制
             * funArr 执行函数
             */
            , execute: function(data) {
                // 初始化
                if(data instanceof Array) {
                    // 设置数据
                    this.data = data;
                }
                this.pause = this.stop = false;
                this.currentIndex = 0;
                // 捕获执行时函数的异常
                let tryExecFun = (fun)=>{
                    try{
                        if(0 < fun) sleep(fun);
                        else fun();
                    }catch(e){
                        console.log(e)
                    }
                }
                // 等待剩余时间
                let waitingTheRemainingTime = (fun, logTag)=>{
                    // 停止
                    if(this.stop) {
                        if(!logTag) console.log("停止播放");
                        // 将下标进度直接设置到底
                        this.currentIndex = this.data.length;
                        // 直接跳出当前的等待
                        return false;
                    // 暂停
                    } else if(this.pause) {
                        if(!logTag) console.log("暂停播放");
                        // 死循环等待
                        setTimeout(()=>{
                            waitingTheRemainingTime(fun)
                        }, 100 * this.precision)
                    // 等待
                    } else if(100 < this.remainingTime) {
                        setTimeout(()=>{
                            this.remainingTime -= 100 * this.precision;
                            waitingTheRemainingTime(fun)
                            // 等待时间，precision用于控制精细度，优化性能
                        }, 100 * this.precision)
                    // 播放
                    } else {
                        fun();
                    }
                }
                // 等待时间
                let timing = ()=>{
                    setTimeout(()=>{
                        if(this.currentIndex < this.data.length) {
                            // 执行当前的函数
                            tryExecFun(this.data[this.currentIndex]);
                            // 下标前移
                            this.currentIndex++;
                            // 等待时间，在时间到了之后就开始下一个 timing 的运行
                            waitingTheRemainingTime(timing)
                        } else {
                            console.log("运行完毕")
                        }
                    }, this.remainingTime * this.precision)
                }
                // 设置时间
                let sleep = (s)=>{
                    if(0 < s) this.remainingTime = s;
                    else console.log("设置延迟失败", s);
                }
                // 正式执行
                console.info("开始执行")
                timing();
            }
        }
        // ================================================
        , mapTemplate:  {
            html: {
                  A1: ()=>{clickPlayKey(0)}
                , A2: ()=>{clickPlayKey(1)}
                , A3: ()=>{clickPlayKey(2)}
                , A4: ()=>{clickPlayKey(3)}
                , A5: ()=>{clickPlayKey(4)}
                , B1: ()=>{clickPlayKey(5)}
                , B2: ()=>{clickPlayKey(6)}
                , B3: ()=>{clickPlayKey(7)}
                , B4: ()=>{clickPlayKey(8)}
                , B5: ()=>{clickPlayKey(9)}
                , C1: ()=>{clickPlayKey(10)}
                , C2: ()=>{clickPlayKey(11)}
                , C3: ()=>{clickPlayKey(12)}
                , C4: ()=>{clickPlayKey(13)}
                , C5: ()=>{clickPlayKey(14)}
                , a1: ()=>{clickPlayKey(0)}
                , a2: ()=>{clickPlayKey(1)}
                , a3: ()=>{clickPlayKey(2)}
                , a4: ()=>{clickPlayKey(3)}
                , a5: ()=>{clickPlayKey(4)}
                , b1: ()=>{clickPlayKey(5)}
                , b2: ()=>{clickPlayKey(6)}
                , b3: ()=>{clickPlayKey(7)}
                , b4: ()=>{clickPlayKey(8)}
                , b5: ()=>{clickPlayKey(9)}
                , c1: ()=>{clickPlayKey(10)}
                , c2: ()=>{clickPlayKey(11)}
                , c3: ()=>{clickPlayKey(12)}
                , c4: ()=>{clickPlayKey(13)}
                , c5: ()=>{clickPlayKey(14)}
            }
            , phone: {
                keyPoint: {
                      x: [780,975,1170,1365,1560]
                    , y: [215,410,605]
                }
                , A1: function(){press(this.keyPoint.x[0], this.keyPoint.x[0], 1)}
                , A2: function(){press(this.keyPoint.x[1], this.keyPoint.x[0], 1)}
                , A3: function(){press(this.keyPoint.x[2], this.keyPoint.x[0], 1)}
                , A4: function(){press(this.keyPoint.x[3], this.keyPoint.x[0], 1)}
                , A5: function(){press(this.keyPoint.x[4], this.keyPoint.x[0], 1)}
                , B1: function(){press(this.keyPoint.x[0], this.keyPoint.x[1], 1)}
                , B2: function(){press(this.keyPoint.x[1], this.keyPoint.x[1], 1)}
                , B3: function(){press(this.keyPoint.x[2], this.keyPoint.x[1], 1)}
                , B4: function(){press(this.keyPoint.x[3], this.keyPoint.x[1], 1)}
                , B5: function(){press(this.keyPoint.x[4], this.keyPoint.x[1], 1)}
                , C1: function(){press(this.keyPoint.x[0], this.keyPoint.x[2], 1)}
                , C2: function(){press(this.keyPoint.x[1], this.keyPoint.x[2], 1)}
                , C3: function(){press(this.keyPoint.x[2], this.keyPoint.x[2], 1)}
                , C4: function(){press(this.keyPoint.x[3], this.keyPoint.x[2], 1)}
                , C5: function(){press(this.keyPoint.x[4], this.keyPoint.x[2], 1)}

                , a1: function(){press(this.keyPoint.x[0], this.keyPoint.x[0], 1)}
                , a2: function(){press(this.keyPoint.x[1], this.keyPoint.x[0], 1)}
                , a3: function(){press(this.keyPoint.x[2], this.keyPoint.x[0], 1)}
                , a4: function(){press(this.keyPoint.x[3], this.keyPoint.x[0], 1)}
                , a5: function(){press(this.keyPoint.x[4], this.keyPoint.x[0], 1)}
                , b1: function(){press(this.keyPoint.x[0], this.keyPoint.x[1], 1)}
                , b2: function(){press(this.keyPoint.x[1], this.keyPoint.x[1], 1)}
                , b3: function(){press(this.keyPoint.x[2], this.keyPoint.x[1], 1)}
                , b4: function(){press(this.keyPoint.x[3], this.keyPoint.x[1], 1)}
                , b5: function(){press(this.keyPoint.x[4], this.keyPoint.x[1], 1)}
                , c1: function(){press(this.keyPoint.x[0], this.keyPoint.x[2], 1)}
                , c2: function(){press(this.keyPoint.x[1], this.keyPoint.x[2], 1)}
                , c3: function(){press(this.keyPoint.x[2], this.keyPoint.x[2], 1)}
                , c4: function(){press(this.keyPoint.x[3], this.keyPoint.x[2], 1)}
                , c5: function(){press(this.keyPoint.x[4], this.keyPoint.x[2], 1)}
            }
        }
    }
    var playKeys = [];
    function clickPlayKey(s) {
        if(!playKeys) {
            // 获取当前的所有key
            playKeys = document.querySelectorAll("#keysArea>div>div");
        }
        // 根据 s 来选择点击哪一个
        playKeys[s].click();
    }
    function startAutoPlay() {
        // 获取当前的谱子
        let score = document.querySelector("#inputScore").value;
        let scoreData = performer.scoreHandle(
            score
            , performer.mapTemplate.html
            , (score)=>{return score.split(/[\s,]/)}
        );
        performer.exec.execute(scoreData);
    }
    function pauseOrAutoPlay(e) {
        performer.exec.pause = !performer.exec.pause;
        e.innerText = performer.exec.pause ? "继续" : "暂停";
    }
    function stopAutoPlay() {
        performer.exec.stop = true;
    }
    function switchOptionsDisplayStatus() {
        let op = document.querySelector("#options");
        console.log(op);
        console.log(op.style.display);
        op.style.display = op.style.display=="none"? "inline":"none";
    }
    window.onload = function(){
        // 刷新视图
        refreshView(switchKey(0), skins)
        setTimeout(()=>{
            permissionsTime = 1000;
        },60*1000)


        //   加载tool   ////////////////////////////////////
        let modeKey = document.querySelector("#modeKey");
        let modeKeyParams = "";
        words.forEach(e=>{
            modeKeyParams += '<button onclick="rv(\''
            + e.word[0]
            + '\')">'
            + e.title.substring(0,e.title.indexOf("@"))
            + '</button>';
        })
        modeKey.innerHTML += modeKeyParams;

        tip(performer.update||"暂无更新介绍",5000,{
            backgroundColor: "#00ff0050",
            width: "25%",
            textAlign: "left"
        })
    }
    // 关键词匹配
    var words = [
        {
            title: "钢琴_默认@404 大佬的音效",
            keyNum: 15,
            word: [
                "默认",
                "default",
                "./wav_default",
                "wav_default"
            ],
            uri: "./wav_default"
        },
        // {
        //     title: ""
        //     keyNum: 8,
        //     word: [
        //         ""
        //     ],
        //     uri: "./"
        // },
        // {
        //     word: [
        //         ""
        //     ],
        //     uri: "./"
        // },
        {
            title: "玩具乐队@音频来自微信弦外小程序",
            keyNum: 15,
            word: [
                "玩具",
                "玩具乐队",
                "wanjuyuedui",
                "./wav_km_13_wanjuyuedui",
                "wav_km_13_wanjuyuedui"
            ],
            uri: "./wav_km_13_wanjuyuedui"
        },
        {
            title: "大提琴@音频来自微信弦外小程序",
            keyNum: 15,
            word: [
                "大提琴",
                "datiqin",
                "./wav_km_12_datiqin",
                "wav_km_12_datiqin"
            ],
            uri: "./wav_km_12_datiqin"
        },
        {
            title: "阮@音频来自微信弦外小程序",
            keyNum: 15,
            word: [
                "阮",
                "ruan",
                "./wav_km_11_ruan",
                "wav_km_11_ruan"
            ],
            uri: "./wav_km_11_ruan"
        },
        {
            title: "吉的他@音频来自微信弦外小程序",
            keyNum: 15,
            word: [
                "吉他",
                "吉的他",
                "jideta",
                "./wav_km_2_jideta",
                "wav_km_2_jideta"
            ],
            uri: "./wav_km_2_jideta"
        },
        {
            title: "音的盒@音频来自微信弦外小程序",
            keyNum: 15,
            word: [
                "音盒",
                "音乐盒",
                "音的盒",
                "yindehe",
                "./wav_km_3_yindehe",
                "wav_km_3_yindehe"
            ],
            uri: "./wav_km_3_yindehe"
        },
        {
            title: "棒棒棒!@音频来自微信弦外小程序",
            keyNum: 15,
            word: [
                "棒",
                "bbb",
                "棒棒棒",
                "棒棒棒!",
                "棒棒棒！",
                "bangbangbang",
                "./wav_km_4_bangbangbang",
                "wav_km_4_bangbangbang"
            ],
            uri: "./wav_km_4_bangbangbang"
        },
        {
            title: "未来科技@音频来自微信弦外小程序",
            keyNum: 15,
            word: [
                "科技",
                "未来",
                "未来科技",
                "weilaikeji",
                "./wav_km_5_weilaikeji",
                "wav_km_5_weilaikeji"
            ],
            uri: "./wav_km_5_weilaikeji"
        },
        {
            title: "竖琴@音频来自微信弦外小程序",
            keyNum: 15,
            word: [
                "竖的琴",
                "竖琴",
                "shuqin",
                "./wav_km_6_shuqin",
                "wav_km_6_shuqin"
            ],
            uri: "./wav_km_6_shuqin"
        },
        {
            title: "木琴@音频来自微信弦外小程序",
            keyNum: 15,
            word: [
                "木的琴",
                "木琴",
                "muqin",
                "./wav_km_7_muqin",
                "wav_km_7_muqin"
            ],
            uri: "./wav_km_7_muqin"
        },
        {
            title: "梦@音频来自微信弦外小程序",
            keyNum: 15,
            word: [
                "m",
                "梦",
                "meng",
                "./wav_km_8_meng",
                "wav_km_8_meng"
            ],
            uri: "./wav_km_8_meng"
        },
        {
            title: "笛@音频来自微信弦外小程序",
            keyNum: 15,
            word: [
                "d",
                "笛",
                "di",
                "./wav_km_9_di",
                "wav_km_9_di"
            ],
            uri: "./wav_km_9_di"
        },
        {
            title: "8比特@音频来自微信弦外小程序",
            keyNum: 15,
            word: [
                "比特",
                "8比特",
                "8bite",
                "./wav_km_10_8bite",
                "wav_km_10_8bite"
            ],
            uri: "./wav_km_10_8bite"
        },
        {
            title: "钢琴@𓇼 大佬的音效",
            keyNum: 15,
            word: [
                "钢琴",
                "piano",
                "./wav_piano",
                "wav_piano"
            ],
            uri: "./wav_piano"
        },
        {
            title: "钢琴1@游戏内录制，存在杂音",
            keyNum: 15,
            word: [
                "钢琴1",
                "piano1",
                "./wav_piano1",
                "wav_piano1"
            ],
            uri: "./wav_piano1"
        },
        {
            title: "钢琴2@404 大佬的游戏包中提取的音效",
            keyNum: 15,
            word: [
                "钢琴2",
                "piano2",
                "./wav_piano2",
                "wav_piano2"
            ],
            uri: "./wav_piano2"
        },
        {
            title: "竖琴1@游戏内录制，存在杂音",
            keyNum: 15,
            word: [
                "竖琴1",
                "harp",
                "./wav_harp1",
                "wav_harp1"
            ],
            uri: "./wav_harp1"
        },
    ]
    // 皮肤，按钮图的class，中点150，75，半径40
    var skins = {
        ".s1": (ctx, zoom)=>{
            skins[".s2"](ctx,0.8);
            skins[".s3"](ctx,1.3);
        },
        ".s2": (ctx, zoom)=>{
            let r = 40*(zoom||1);
            ctx.ellipse(150, 75, 2*r, r, 0, 0, Math.PI*2);
        },
        ".s3": (ctx, zoom)=>{
            let offsetX = 40*(zoom||1);
            let offsetY = 10*(zoom||1);
            // 4个点 中点150，75，半径40，
            ctx.moveTo(150-1, (75-40)-offsetY);
            ctx.lineTo(190+offsetX, 75);
            ctx.lineTo(150, (75+40)+offsetY);
            ctx.lineTo(110-offsetX, 75);
            ctx.lineTo(150+1, (75-40)-offsetY);
        },
        ".s4": (ctx)=>{skins[".s2"](ctx);},
        ".s5": (ctx)=>{skins[".s3"](ctx);},
        ".s6": (ctx)=>{skins[".s2"](ctx);},
        ".s7": (ctx)=>{skins[".s3"](ctx);}
    }
    // 快速切换音频模式
    function rv(key, ski) {
        if(typeof key != "object") {
            try{
                return refreshView(switchKey(key), ski);
            }catch(e){
                console.warn(e);
            }
        }
        refreshView(key, ski);
    }

    var permissionsTime = 5000;
    // 音频缓存
    var playCaches = {};
    // 获取到当前显示的界面
    var ka = document.querySelector("#keysArea");
    if(!ka) {
        // 创建一个div放到body最前面
        document.body.innerHTML =  '<div id="keysArea"></div>' + document.body.innerHTML;
        ka = document.querySelector("#keysArea");
    }

    // 15键
    function key15(url) {
        return {
            urls: [
                [
                    url+"/A1.wav",
                    url+"/A2.wav",
                    url+"/A3.wav",
                    url+"/A4.wav",
                    url+"/A5.wav"
                ],
                [
                    url+"/A6.wav",
                    url+"/A7.wav",
                    url+"/B1.wav",
                    url+"/B2.wav",
                    url+"/B3.wav"
                ],
                [
                    url+"/B4.wav",
                    url+"/B5.wav",
                    url+"/B6.wav",
                    url+"/B7.wav",
                    url+"/C1.wav"
                ]
            ],
            skinLen: 7,
        }
    }
    // 8键
    function key8(url) {
        return {
            urls: [
                [
                    url+"/A1.wav",
                    url+"/A2.wav",
                    url+"/A3.wav",
                    url+"/A4.wav"
                ],
                [
                    url+"/A5.wav",
                    url+"/A6.wav",
                    url+"/A7.wav",
                    url+"/A8.wav"
                ],
            ],
            skinLen: 4,
        }
    }
    // 选择按键
    function switchKey(word) {
        tip("音频来源网络，如有侵权请联系删除！", permissionsTime, {
            backgroundColor: "#ff000050",
            position: "absolute",
            top: "1%",
            left: "1%"
        });
        let chooseKeys;
        // 按照关键词查
        for (const w of words) {
            if(-1 < w.word.indexOf(word)) {
                chooseKeys = w;
            }
        }
        // 按照下标查
        if(!chooseKeys && typeof word == "number" && -1 < word && word < words.length) {
            chooseKeys = word;
        }
        
        // 使用第一个
        if(!chooseKeys) {
            chooseKeys = words[0];
        }

        // 进行生成
        document.querySelector("#bulletin").innerHTML = chooseKeys.title.replace("@", "<br>@");
        return chooseKeys.keyNum == 8 ? key8(chooseKeys.uri) : key15(chooseKeys.uri);
    }

    // 通过按键以及皮肤刷新界面
    function refreshView(key, ski) {
        key = key || keys;
        ski = ski || skins;
        // 清除界面
        ka.innerHTML = "";
        // 渲染页面
        loadView(key);
        // 添加动画
        addSkin(ski);
    }
    // 加载界面，同时加载音频
    function loadView(keys) {
        let skinNum = 0;
        keys.urls.forEach(ks => {
            if(!(ks instanceof Array)) ks = [ks];
            let line = document.createElement("div");
            ks.forEach(k=>{
                let kDiv = document.createElement("div");
                let kCan = document.createElement("canvas");
                kDiv.setAttribute("onclick", "play(this, '"+k+"')");
                kDiv.className = "off";
                skinNum = skinNum < keys.skinLen? skinNum+1 : 1;
                kCan.className = "s"+ skinNum;
                kDiv.appendChild(kCan);
                line.appendChild(kDiv);
                playKeys.push(kDiv);
                // 加载音频
                if(!(playCaches[k])) {
                    play(kDiv, k, "download");
                }
            })
            ka.appendChild(line);
        })
    }
    // 播放
    function play(e, uri, download) {
        let num = 0;
        let clearAnim = function(e){
            if(num < 10){
                setTimeout(()=>{
                    e.style.backgroundColor = "#" + ((10 - num)<10?(10 - num):9) + "0ff0011";
                    num++;
                    clearAnim(e);
                }, 30)
            } else {
                setTimeout(()=>{
                    e.style.backgroundColor = "";
                },100)
            }
        }
        clearAnim(e);
        if(playCaches[uri]) {
            if(!download) playCaches[uri]();
            if(e.className.indexOf("on") < 0) {
                e.className += " on";
            }
        } else {
            tip("正在下载..."+uri.substring(uri.lastIndexOf("/")+1), 334);
            let au = document.createElement("audio");
            au.src = uri;
            au.canplaythrough = e.className += " on";
            playCaches[uri] = function(v) {
                if(typeof v == "number" && 0 <= v && v <= 1) {
                    au.volume = v;
                } else {
                    au.currentTime = 0;
                    au.play();
                }
            }
        }
    }
    // 添加皮肤
    function addSkin(skins) {
        for (let key in skins) {
            let s = document.querySelectorAll(key);

            s.forEach(c=>{
                let ctx = c.getContext("2d");
                ctx.beginPath();
                ctx.strokeStyle = "#E4C8A3";
                // ctx.fillStyle="#FF0000";
                ctx.lineWidth = 7;
                // ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise)
                // arc(x,y,r,start,stop)
                // ctx.arc(150,75,70,0,2*Math.PI);
                skins[key](ctx)
                ctx.stroke();
            })
        }
    }

    // 提示框
    function tip(message,time,style) {
        if(typeof style != "object") style = {};
        if(-1 < time);
        else time = 2000;
        // 创建一个div，将其展示在最顶层
        let d = document.createElement("div");
        d.innerHTML = message;
        d.setAttribute("id","showTip");
        d.setAttribute("onclick","try{this.parentElement.removeChild(this);}catch(e){}");
        d.style.width = style.width || "10%";
        d.style.heigth = style.heigth || "10%";
        d.style.backgroundColor = style.backgroundColor || "cornflowerblue";
        d.style.borderRadius = style.borderRadius || "10px";
        d.style.padding = style.padding || "10px";
        d.style.position = style.position || "fixed";
        d.style.float = style.float || "left";
        d.style.zIndex = style.zIndex || "9999999999";
        d.style.left = style.left || "40%";
        d.style.right = style.right || "auto";
        d.style.top = style.top || "10%";
        d.style.bottom = style.bottom || "auto";
        d.style.overflow = style.overflow || "hidden";
        d.style.textAlign = style.textAlign || "center";
        document.body.appendChild(d);
        setTimeout(()=>{d.click()},time)
    }

    var volume = true;
    // 设置音量
    function setVolumeNum(param) {
        volume = param!=undefined ? param : volume;
        for (const key in playCaches) {
            playCaches[key](volume ? 0 : 1);
        }
        document.getElementById("setvolume").value = volume ? "静音" : "声音";
        volume = !volume;
    }
    var tool = document.querySelector("#tool");
</script>

<style>
    #tool{
        /* display: none; */
    }
    #modeKey>*{
        margin: 3px;
    }
    
    html{
        background-image: linear-gradient(black, #568FAA, #ffffff, #ffffff);
        background-repeat: no-repeat;
    }
    body{
        text-align: center;
        padding-top: 7%;
    }
    /* #keysArea{
        border-radius: 5%;
        border: 1px solid #695d45;
        padding: 1% 0;
    } */
    #keysArea>div>*{
        display: inline-block;
        width: 3.6rem;
        height: 3.6rem;
        margin: 2px;
        overflow: hidden;
        border-radius: 20%;/*设置圆角*/
    }
    canvas{
        width: 3.6rem;
        height: 3.6rem;
    }
    canvas{
        transform:rotate(0deg);
        transition: transform .2s;
        transform-origin: center center;
    }
    canvas:active{
        transform:rotateY(180deg);
    }
    .off{
        background-color: #3c3c3c20;
    }
    .on{
        background-color: #faebd720;
    }

    .noCopy{
        user-select:none;
        -webkit-user-select:none;
    }
    .copy{
        user-select:auto;
        -webkit-user-select:auto;
    }
    .inputTextarea{
        margin-top: 1%;
    }
    .inputUO{
        width: 20%;
    }

    /* ====================== */
    #tool{
        border: 1px solid rgb(182, 146, 79);
        border-radius: 7px;
    }
</style>